﻿using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Syndication;
using System.ServiceModel.Web;
using NCMIS.ObjectModel;
using NCMIS.ObjectModel.Rest;
using NCMIS.Provider;
using NCMIS.ServiceModel.Syndication;
using NCMIS.ObjectModel.MetaData;

namespace NCMIS.ServiceModel.Ra
{
    /// <summary>
    /// Provides the Relationship Services for the REST/Atom binding. The relationship services are used to retrieve the dependent Relationship objects
    /// associated with an independent object.
    /// </summary>
    public partial class Service : IService
    {
        /// <summary>
        /// Gets all or a subset of relationships associated with an independent object.
        /// </summary>
        /// <param name="repositoryId">The id of the repository.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="includeSubRelationshipTypes">If true, then the Repository must return all relationships whose Object-Types are descendant-types
        /// of the given object's cmis:objectTypeId property value.  If FALSE, then the Repository MUST only return relationships whose Object-Type is
        /// equivalent to the given object’s cmis:objectTypeId property value.</param>
        /// <param name="relationshipDirection">Specifies whether the Repository MUST return relationships where the specified Object is the source of
        /// the relationship, the target of the relationship, or both.</param>
        /// <param name="typeId"> If specified, then the Repository must return only relationships whose Object-Type is of the type specified.</param>
        /// <param name="filter">Value indicating which properties for Objects that must be returned.</param>
        /// <param name="includeAllowableActions">If true, then the the available actions for each object in the result set must be returned. (Optional, default: false)</param>
        /// <param name="maxItems">The maximum number of items to return in the response. (optional, default: repository specific)</param>
        /// <param name="skipCount">The number of potential results to skip before returning any results. (optional, default: 0)</param>
        /// <returns>Relationships associated with an independent object, formatted as Atom 1.0 Feed.</returns>
        [WebGet(UriTemplate = "/{repositoryId}/object/{objectId}/relationships")]
        public Atom10FeedFormatter GetObjectRelationships(string repositoryId, string objectId)
        {
            bool includeSubRelationshipTypes = RequestParameter.IncludeSubRelationshipTypes;
            RelationshipDirection relationshipDirection = RequestParameter.RelationshipDirection;
            string typeId = RequestParameter.TypeId;
            string filter = RequestParameter.Filter;
            bool includeAllowableActions = RequestParameter.IncludeAllowableActions;
            int? maxItems = RequestParameter.MaxItems;
            int skipCount = RequestParameter.SkipCount;

            OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse;
            ctx.ContentType = CmisContentType.Feed;

            // Repository ID and object ID must be specified
            if (String.IsNullOrEmpty(repositoryId) || String.IsNullOrEmpty(objectId))
            {
                ctx.StatusCode = ServiceException.InvalidArgument;
                ctx.StatusDescription = String.Format("{0}: The parameters repositoryId and folderId must not be null or empty.",
                    ServiceException.InvalidArgument.ToString());
                return null;
            }

            // Store the object relationships in a CmisObjectList
            CmisObjectList cmisObjectList = RelationshipProviderManager.Provider.GetObjectRelationships(repositoryId, objectId, includeSubRelationshipTypes,
                    relationshipDirection, typeId, filter, includeAllowableActions, maxItems, skipCount);

            // Create a feed to hold list content
            CmisSyndicationFeed feed = new CmisSyndicationFeed()
            {
                BaseUri = _baseUri,
                Id = "urn:uuid:base-types",
                RepositoryId = repositoryId,
                SelfLinkUri = new Uri(_baseUri, String.Format("{0}/types", repositoryId)),
                ServiceLinkUri = new Uri(_baseUri, String.Format("{0}/servicedoc", repositoryId)),
                Title = new TextSyndicationContent("Base Types"),
            };
            feed.AddEntries(cmisObjectList);
            feed.AddNumItems();

            // Format the feed as an Atom feed
            return new Atom10FeedFormatter(feed);
        }
    }
}
